#pragma once
#include "rpc_requestor.hpp"

namespace RPC
{
    namespace Client
    {
        class RpcCaller
        {
        public:
            using Ptr = std::shared_ptr<RpcCaller>;
            using JsonAsyncResponse = std::future<Json::Value>;
            using JsonCallback = std::function<void(const Json::Value &)>;
            RpcCaller(const Requestor::Ptr &request) : _requestor(request) {}

            bool call(const BaseConnection::Ptr &conn, const std::string &method, const Json::Value &params, Json::Value &result)
            {
                // 1、组织构建请求
                RpcRequest::Ptr req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setParam(params);
                req->setMethod(method);
                req->setType(MType::REQ_RPC);

                BaseMessage::Ptr resp;
                // 2、发送请求
                ERROR_LOG("发送了一条RPC_REQ");
                bool ret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req), resp);
                if (ret == false)
                    return false;
                RpcResponse::Ptr rpc_resp = std::dynamic_pointer_cast<RpcResponse>(resp);
                if (rpc_resp == nullptr)
                {
                    ERROR_LOG("向下强转失败!");
                    return false;
                }
                if (rpc_resp->rCode() != RCode::RCODE_OK)
                {
                    ERROR_LOG("返回值错误！");
                    return false;
                }
                // 3、处理结果
                result = rpc_resp->Result();
                return true;
            }

            bool call(const BaseConnection::Ptr &conn, const std::string &method, const Json::Value &params, JsonAsyncResponse &result)
            {
                // 1、组织构建请求
                RpcRequest::Ptr req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setParam(params);
                req->setMethod(method);
                req->setType(MType::REQ_RPC);

                // 2、发送请求
                std::shared_ptr<std::promise<Json::Value>> pro = std::make_shared<std::promise<Json::Value>>();
                result = pro->get_future();
                Requestor::RequestCallback x = bind(&RpcCaller::asyncCallback, this, pro, std::placeholders::_1);
                bool sendret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req), x);
                if(sendret == false)
                {
                    ERROR_LOG("发送错误！");
                    return false;
                }
                return true;
            }

            bool call(const BaseConnection::Ptr &conn, const std::string &method, const Json::Value &params, const JsonCallback &call)
            {
                                // 1、组织构建请求
                RpcRequest::Ptr req = MessageFactory::create<RpcRequest>();
                req->setId(UUID::uuid());
                req->setParam(params);
                req->setMethod(method);
                req->setType(MType::REQ_RPC);

                // 2、发送请求
                Requestor::RequestCallback x = bind(&RpcCaller::callback, this,  call, std::placeholders::_1);
                bool sendret = _requestor->send(conn, std::dynamic_pointer_cast<BaseMessage>(req), x);
                if(sendret == false)
                {
                    ERROR_LOG("发送错误！");
                    return false;
                }
                return true;
            }

        private:
            void callback(JsonCallback call, const BaseMessage::Ptr& msg)
            {
                RpcResponse::Ptr msg_resp = std::dynamic_pointer_cast<RpcResponse>(msg);
                if(msg_resp == nullptr)
                {
                    ERROR_LOG("向下转化失败！");
                    return;
                }
                if(msg_resp->rCode() != RCode::RCODE_OK)
                {
                    ERROR_LOG("返回值类型错误！");
                    return;
                }
                call(msg_resp->Result());
            }
            void asyncCallback(std::shared_ptr<std::promise<Json::Value>> pro, const BaseMessage::Ptr& msg)
            {
                RpcResponse::Ptr resp = std::dynamic_pointer_cast<RpcResponse>(msg);
                if(resp == nullptr)
                {
                    ERROR_LOG("动态指针转换失败!");
                    return;
                }
                if(resp->rCode() != RCode::RCODE_OK)
                {
                    std::cout << "resp code: " << (int)resp->rCode() << std::endl;
                    ERROR_LOG("返回值类型错误!");
                    return;
                }
                pro->set_value(resp->Result());
                return;
            }
            Requestor::Ptr _requestor;
        };
        
        class CallerFactory
        {
        public:
            template<typename ...Args>
            static RpcCaller::Ptr create(Args ...args)
            {
                return std::make_shared<RpcCaller>(args...);
            }
        };
    }
}